package cn.neusoft.service.impl;

import cn.neusoft.domain.Menu;
import cn.neusoft.domain.Operator;
import cn.neusoft.exception.AppException;
import cn.neusoft.exception.AppExceptionCodeMsg;
import cn.neusoft.mapper.LoginMapper;
import cn.neusoft.service.LoginService;
import cn.neusoft.util.SmsConstantUtils;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import com.tencentcloudapi.sms.v20210111.models.SendStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Slf4j
public class LoginServiceImpl implements LoginService {

    @Autowired
    LoginMapper loginMapper;

    @Autowired
    private SmsConstantUtils smsConstantUtils;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    @Transactional
    @Override
    public Operator findByAccount(String operator_account) {
        return loginMapper.findByAccount(operator_account);
    }

    @Transactional
    @Override
    public Operator findByTel(String tel) {
        return loginMapper.findByTel(tel);
    }

    @Transactional
    @Override
    public Map<String, Object> loginByPwd(String operator_account, String operator_password) {

        Operator operator = loginMapper.findByAccount(operator_account);

        // 账号不存在
        if (operator == null) {
            throw new AppException(AppExceptionCodeMsg.OPERATOR_ACCOUNT_NOT_EXITS);
        }

        // 账号密码不匹配
        if (!Objects.equals(operator_password, operator.getOperator_password())) {
            throw new AppException(AppExceptionCodeMsg.OPERATOR_ACCOUNT_PASSWORD_WRONG);
        }

        // 登录成功
        List<Menu> menuList = loginMapper.getMenuListByRoleId(String.valueOf(operator.getRole_id()));
        Map<String, Object> map = new HashMap<>();
        map.put("user", operator);
        map.put("menu", menuList);

        return map;
    }


    @Transactional
    @Override
    public Map<String, Object> loginByTel(String tel, String code) {
        Operator operator = loginMapper.findByTel(tel);

        // 手机号不存在
        if (operator == null){
            throw new AppException(AppExceptionCodeMsg.OPERATOR_TEL_NOT_EXITS);
        }

        // 验证码错误
        if(!Objects.equals(code, redisTemplate.opsForValue().get(tel))){
            throw new AppException(AppExceptionCodeMsg.INVOID_CODE);
        }

        // 登录成功
        List<Menu> menuList = loginMapper.getMenuListByRoleId(String.valueOf(operator.getRole_id()));
        Map<String, Object> map = new HashMap<>();
        map.put("user", operator);
        map.put("menu", menuList);

        return map;
    }


    @Transactional
    @Override
    public void send(String phone, String[] params) {
        String phoneNumber = "+86" + phone;
        String secretId = smsConstantUtils.getSecretId();
        String secretKey = smsConstantUtils.getSecretKey();
        String sdkAppId = smsConstantUtils.getSdkAppId();
        String signName = smsConstantUtils.getSignName();
        String templateId = smsConstantUtils.getTemplateId();

        String[] phoneNumberSet = {phoneNumber};
        String[] templateParamSet = params;//对应模板中{1}{2}

        try {
            /* 必要步骤：
             * 实例化一个认证对象，入参需要传入腾讯云账户密钥对secretId，secretKey。
             * 这里采用的是从环境变量读取的方式，需要在环境变量中先设置这两个值。
             * 你也可以直接在代码中写死密钥对，但是小心不要将代码复制、上传或者分享给他人，
             * 以免泄露密钥对危及你的财产安全。
             * SecretId、SecretKey 查询: https://console.cloud.tencent.com/cam/capi */
            Credential cred = new Credential(secretId, secretKey);

            // 实例化一个http选项，可选，没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            // 设置代理（无需要直接忽略）
            // httpProfile.setProxyHost("真实代理ip");
            // httpProfile.setProxyPort(真实代理端口);
            /* SDK默认使用POST方法。
             * 如果你一定要使用GET方法，可以在这里设置。GET方法无法处理一些较大的请求 */
            httpProfile.setReqMethod("POST");
            /* SDK有默认的超时时间，非必要请不要进行调整
             * 如有需要请在代码中查阅以获取最新的默认值 */
            httpProfile.setConnTimeout(60);
            /* 指定接入地域域名，默认就近地域接入域名为 sms.tencentcloudapi.com ，也支持指定地域域名访问，例如广州地域的域名为 sms.ap-guangzhou.tencentcloudapi.com */
            httpProfile.setEndpoint("sms.tencentcloudapi.com");

            /* 非必要步骤:
             * 实例化一个客户端配置对象，可以指定超时时间等配置 */
            ClientProfile clientProfile = new ClientProfile();
            /* SDK默认用TC3-HMAC-SHA256进行签名
             * 非必要请不要修改这个字段 */
            clientProfile.setSignMethod("HmacSHA256");
            clientProfile.setHttpProfile(httpProfile);
            /* 实例化要请求产品(以sms为例)的client对象
             * 第二个参数是地域信息，可以直接填写字符串ap-guangzhou，支持的地域列表参考 https://cloud.tencent.com/document/api/382/52071#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8 */
            SmsClient client = new SmsClient(cred, "ap-guangzhou", clientProfile);
            /* 实例化一个请求对象，根据调用的接口和实际情况，可以进一步设置请求参数
             * 你可以直接查询SDK源码确定接口有哪些属性可以设置
             * 属性可能是基本类型，也可能引用了另一个数据结构
             * 推荐使用IDE进行开发，可以方便的跳转查阅各个接口和数据结构的文档说明 */
            SendSmsRequest req = new SendSmsRequest();

            /* 填充请求参数,这里request对象的成员变量即对应接口的入参
             * 你可以通过官网接口文档或跳转到request对象的定义处查看请求参数的定义
             * 基本类型的设置:
             * 帮助链接：
             * 短信控制台: https://console.cloud.tencent.com/smsv2
             * 腾讯云短信小助手: https://cloud.tencent.com/document/product/382/3773#.E6.8A.80.E6.9C.AF.E4.BA.A4.E6.B5.81 */

            /* 短信应用ID: 短信SdkAppId在 [短信控制台] 添加应用后生成的实际SdkAppId，示例如1400006666 */
            // 应用 ID 可前往 [短信控制台](https://console.cloud.tencent.com/smsv2/app-manage) 查看
            req.setSmsSdkAppId(sdkAppId);

            /* 短信签名内容: 使用 UTF-8 编码，必须填写已审核通过的签名 */
            // 签名信息可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-sign) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-sign) 的签名管理查看
            req.setSignName(signName);

            /* 模板 ID: 必须填写已审核通过的模板 ID */
            // 模板 ID 可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-template) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-template) 的正文模板管理查看
            req.setTemplateId(templateId);

            /* 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致，若无模板参数，则设置为空 */
            req.setTemplateParamSet(templateParamSet);

            /* 下发手机号码，采用 E.164 标准，+[国家或地区码][手机号]
             * 示例如：+8613711112222， 其中前面有一个+号 ，86为国家码，13711112222为手机号，最多不要超过200个手机号 */
            req.setPhoneNumberSet(phoneNumberSet);

            /* 通过 client 对象调用 SendSms 方法发起请求。注意请求方法名与请求对象是对应的
             * 返回的 res 是一个 SendSmsResponse 类的实例，与请求对象对应 */
            SendSmsResponse res = client.SendSms(req);
            //获取响应结果
            SendStatus[] sendStatusSet = res.getSendStatusSet();
            // 输出json格式的字符串回包
            System.out.println(SendSmsResponse.toJsonString(res));
            log.info("短信发送返回的响应："+ Arrays.toString(sendStatusSet));
        } catch (TencentCloudSDKException e) {
            log.error("腾讯云短信发送sdk调用失败："+e.getErrorCode()+","+e.getMessage());
            throw new AppException(AppExceptionCodeMsg.CODE_SEND_FAILED);
        }
    }
}
